#ifndef __THREAD_POOL_H__
#define __THREAD_POOL_H__

#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>
#include <memory>
#include <thread>

class ThreadPool
{
public:
    // 创建n个线程并detach
    // 每个线程循环从任务队列取任务
    ThreadPool(int thread_num = 8) : pool_(std::make_shared<Pool>())
    {
        pool_->isClose = false;

        for (int i = 0; i < thread_num; i++)
        {
            std::thread([pool = pool_]
                        {
                            std::unique_lock<std::mutex> lock(pool->mutex);
                            while (true)
                            {
                                // TODO
                                if(!pool->task_queue.empty()) {
                                    auto task = std::move(pool->task_queue.front());
                                    pool->task_queue.pop();
                                    lock.unlock();
                                    task();
                                    lock.lock();
                                } else if(pool->isClose) {
                                    break;
                                } else {
                                    pool->cond.wait(lock);
                                }
                            } })
                .detach();
        }
    }
    ~ThreadPool()
    {
        if (static_cast<bool>(pool_))
        {
            {
                std::unique_lock<std::mutex> lock(pool_->mutex);
                pool_->isClose = true;
            }
            pool_->cond.notify_all();
        }
    }

    template<class F>
    void add_task(F&& task)
    {
        {
            std::lock_guard<std::mutex> lock(pool_->mutex);
            pool_->task_queue.emplace(std::forward<F>(task));
        }
        pool_->cond.notify_one();
    }

private:
    struct Pool
    {
        std::mutex mutex;
        std::condition_variable cond;
        bool isClose;
        std::queue<std::function<void()>> task_queue;
    };

    std::shared_ptr<Pool> pool_;
};
#endif